package cn.yitun.chat.yitunserverrunsingleboot.chat.common.interceptor;


import cn.yitun.chat.yituncommonmessage.ExceptionEnum;
import cn.yitun.chat.yituncommonmessage.YitunException;
import cn.yitun.chat.yitunservercommonlib.exception.ErrorResultMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;


/**
 * 全局方法异常处理器
 */
//@Order(-1)
//@RestControllerAdvice
@Slf4j
public class RExceptionHandler {

    /**
     * 日志保存异常信息
     *
     * @param e
     */
    private void logErr(Exception e) {
        log.error(e.getMessage(), e);
    }

    /**
     * 全局异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public ErrorResultMessage handleException(Exception e) {
        ErrorResultMessage result = new ErrorResultMessage();
        result.addError(ExceptionEnum.UNKNOW_ERROR.getCode().toString(),ExceptionEnum.UNKNOW_ERROR.getMsg());
        logErr(e);
        e.printStackTrace();
        return result;
    }

    /**
     * 自定义异常
     */
    @ExceptionHandler(YitunException.class)
    public ErrorResultMessage handleRRException(YitunException e) {
//        logErr(e);
        ErrorResultMessage r = new ErrorResultMessage();
        r.addError(String.valueOf(e.getCode()), e.getMsg());
        return r;
    }

    /**
     * 请求方法异常
     *
     * @return
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public ErrorResultMessage handleMethodNotException(HttpRequestMethodNotSupportedException e) {
        ErrorResultMessage r = new ErrorResultMessage();
        logErr(e);
        r.addError(ExceptionEnum.HTTP_METHOD_NOT_SUPPORT.getCode().toString(), ExceptionEnum.HTTP_METHOD_NOT_SUPPORT.getMsg());
        return r;
    }

    /**
     * 参数校验失败的异常
     *
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ErrorResultMessage handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        logErr(e);
        e.printStackTrace();
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        StringBuilder stringBuffer = new StringBuilder();
        for (ObjectError allError : allErrors) {
            stringBuffer.append(allError.getDefaultMessage()).append(";");

        }
        ErrorResultMessage r = new ErrorResultMessage();
        r.addError("-100", stringBuffer.toString());
        return r;
    }

    /**
     * http body参数无法读取转换
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ErrorResultMessage handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
        logErr(e);
        e.printStackTrace();
        ErrorResultMessage r = new ErrorResultMessage();
        r.addError(ExceptionEnum.HTTP_BODY_NOT_READABLE.getCode().toString(), ExceptionEnum.HTTP_BODY_NOT_READABLE.getMsg());
        return r;
    }

    /**
     * mysql语法错误
     *
     * @return
     */
    @ExceptionHandler(BadSqlGrammarException.class)
    public ErrorResultMessage handleBadSqlGrammarException(BadSqlGrammarException e) {
        logErr(e);
        e.printStackTrace();
        ErrorResultMessage r = new ErrorResultMessage();
        r.addError(ExceptionEnum.MYSQL_SQL_GRAMMAR_ERROR.getCode().toString(), ExceptionEnum.MYSQL_SQL_GRAMMAR_ERROR.getMsg());
        return r;
    }

    /**
     * 服务器参数异常，一般是因为少传了参数导致
     *
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ErrorResultMessage handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        logErr(e);
        ErrorResultMessage r = new ErrorResultMessage();
        r.addError(ExceptionEnum.HTTP_PARAMETER_ERROR.getCode().toString(), ExceptionEnum.HTTP_PARAMETER_ERROR.getMsg());
        return r;
    }

    /**
     * 方法级别的参数校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ErrorResultMessage handleConstraintViolationException(ConstraintViolationException e) {
        logErr(e);
        e.printStackTrace();
        StringBuilder eMsg = new StringBuilder();
        for (ConstraintViolation<?> constraintViolation : e.getConstraintViolations()) {
            eMsg.append(constraintViolation.getMessage()).append(";");
        }
        ErrorResultMessage r = new ErrorResultMessage();
        r.addError("-100", eMsg.toString());
        return r;
    }

    /**
     * 绑定的方法参数异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(BindException.class)
    public ErrorResultMessage handleBindException(BindException e) {
        logErr(e);
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        StringBuilder stringBuffer = new StringBuilder();
        for (ObjectError allError : allErrors) {
            stringBuffer.append(allError.getDefaultMessage()).append(";");
        }
        ErrorResultMessage r = new ErrorResultMessage();
        r.addError("-100", stringBuffer.toString());
        return r;
    }

    /**
     * 方法参数无法转换异常，通常为定义一个Bol 类型的值，传过来的参数无法转换为bol  如null string int>2
     *
     * @return
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ErrorResultMessage handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
        logErr(e);
        e.printStackTrace();
        ErrorResultMessage r = new ErrorResultMessage();
        r.addError(ExceptionEnum.METHOD_ARGUMENT_TYPE_MISMATCH_ERROR.getCode().toString(), ExceptionEnum.METHOD_ARGUMENT_TYPE_MISMATCH_ERROR.getMsg());
        return r;

    }
}


